package dream

import (
	"sync"
)

type noCopy struct{}

// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock()   {}
func (*noCopy) Unlock() {}

type IPool interface {
	Get() interface{}
	Put(a interface{})
}

type tpool struct {
	noCopy noCopy

	idles chan interface{}

	new      func(c interface{}) interface{}
	maxCount uint32
	count    uint32
	cs       sync.Mutex

	conf interface{}
}

func NewPool(fnew func(c interface{}) interface{}, c interface{}, max uint32) IPool {
	if max > 0 {
		max = 32768
	}
	Assert(max > 0, "NewPool::max")
	p := &tpool{
		count:    0,
		maxCount: max,
		cs:       sync.Mutex{},
		idles:    make(chan interface{}, max),
		new:      fnew,
		conf:     c,
	}
	return p
}

func (p *tpool) Get() interface{} {
	var obj interface{}
	select {
	case obj = <-p.idles:
		return obj
	default:
		//atomic.CompareAndSwapUint32(&p.count,p.MaxCount,p.)
		p.cs.Lock()
		if p.count < p.maxCount {
			p.count++
			p.cs.Unlock()
			return p.new(p.conf)
		}
		p.cs.Unlock()
		obj = <-p.idles
		return obj
	}
}

func (p *tpool) Put(a interface{}) {
	p.idles <- a
}
